﻿// 为了方便管理，就将[Code]区段单独拿出来了
// innosetup 支持的颜色值
// clBlack（黑色），clMaroon（暗红），clGreen（绿色），clOlive（橄榄绿），
// clNavy（深蓝），clPurple（紫色），clTeal（深青），clGray（灰色），
// clSilver（浅灰），clRed（红色），clLime（浅绿），clYellow（黄色），
// clBlue （蓝色），clFuchsia（紫红），clAqua（青绿），clWhite（白色）。
// 引入botva2的函数声明
#include "./event_handle.iss"

//系统配置属性
const
    PRODUCT_REGISTRY_KEY = 'SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\{#MyAppID}_is1';
    WM_SYSCOMMAND = $0112;
    ID_BUTTON_ON_CLICK_EVENT = 1;
    CS_DROPSHADOW = 131072;
    GCL_STYLE = -26;

//UI基础属性设置
const
    WIZARDFORM_WIDTH_NORMAL = 660;
    WIZARDFORM_HEIGHT_NORMAL = 480;
    WIZARDFORM_HEIGHT_MORE = 600;
    WIZARDFORM_BORDER_WIDTH = 1;
    CUSTOMFORM_WIDTH_NORMAL = 400;
    CUSTOMFORM_HEIGHT_NORMAL = 154;
    MAIN_WIN_MOUSE_DRAGGABLE_HEIGHT = 60;


//主窗口UI属性
var
    app_name_label: TLabel;             // 软件标题
    app_name_font: TFont;               // 软件标题
    mainBkPanel: TPanel;                // 主窗口背景
    label_wizardform_main: TLabel;      // 主界面背景点击相应
    button_minimize: HWND;              // 最小化按钮
    button_close: HWND;                 // 关闭按钮
    versionBk: TLabel;                  // 版本背景
    label_version: TLabel;              // 版本号
    button_install_now: HWND;           // 立马安装
    button_install_now_font: TFont;     // 立马按照按钮字体
    label_error_tips: TLabel;           // 安装tips: 1.路径无效？ 2.内存不足？

//许可证复选框数据
var
    checkbox_license: HWND;             // license checkbox
    label_agree_title: TLabel;          // agree title
    label_agree_content: TLabel;        // 条款

//安装升级失败时提示
var
    update_failed_title: TLabel;        // 标题
    update_failed_disc: TLabel;         // 描述
    update_failed_link: TLabel;         // 描述

//更多选择按钮数据
var
    btn_more_options: HWND;             // 更多选择按钮
    btn_more_options_arrow: HWND;       // 更多选择按钮下拉箭头
    btn_more_options_font: TFont;       // 更多选择的文本
    btn_more_options_close: HWND;       // 更多选择按钮
    btn_more_options_font_1: TFont;     // 更多选择的文本
    btn_more_option: TLabel;            // 更多选择按钮的标签
    label_need_space: TLabel;           // 需要的空间label
    label_disk_space: TLabel;           // 磁盘的空间label
    edit_target_path: TEdit;            // 路径选择
    edit_target_path_bg: LONGINT;       // 路径选择背景
    button_browse: HWND;                // 系统文件管理窗口弹出按钮
    button_browse_font: TFont;          // 系统文件管理窗口弹出按钮文案
    label_warn_tips: TLabel;            // 安装路径选择相关错误提示
    label_install_progress: TLabel;     // 进度条
    button_run_now: HWND;               // 立马运行
    button_run_now_font: TFont;         // 立马运行文本

var
    button_messagebox_ok_font: TFont;
    button_messagebox_yes_font: TFont;
    button_messagebox_no_font: TFont;
    button_messagebox_continue_font: TFont;
    button_messagebox_teminate_font: TFont;

//测试控件
var
    btn_test: TButton;
    checkbox_test: TCheckBox;

// messagebox
var
    messagebox_close: TSetupForm;
    closeBkPanel: TPanel;                        // messagebox
    image_message_background: LONGINT;
    label_messagebox_main: TLabel;
    label_messagebox_information: TLabel;
    button_messagebox_ok: HWND;
    button_messagebox_yes: HWND;
    button_messagebox_no: HWND;
    button_messagebox_continue: HWND;
    button_messagebox_teminate: HWND;

// custom var
var
    image_wizardform_background: LONGINT;
    image_version_background: LONGINT;
    dNeedSpaceByte: Int64;                       // 需要的安装的空间大小，（字节)
    image_progressbar_background: LONGINT;
    image_progressbar_foreground: LONGINT;
    can_exit_setup: BOOLEAN;
    can_next_setup: BOOLEAN;
    PBOldProc: LONGINT;
    button_messagebox_cancel: HWND;
    isFirst, is_wizardform_show_normal, is_installer_initialized, is_platform_windows_7, is_wizardform_released: BOOLEAN;
    version_installed_before : STRING;

var
    UninstallFirstPage: TNewNotebookPage;
    UninstallSecondPage: TNewNotebookPage;
    UninstallBackButton: TNewButton;
    UninstallNextButton: TNewButton;


//释放需要的临时资源文件
PROCEDURE extract_temp_files();
BEGIN
    ExtractTemporaryFile('button_close.png');
    ExtractTemporaryFile('button_minimize.png');
    ExtractTemporaryFile('install_right_now.png');
    ExtractTemporaryFile('install_right_now_1.png');
    ExtractTemporaryFile('run_now.png');
    ExtractTemporaryFile('run_now_1.png');
    ExtractTemporaryFile('bk_white2.png');
    ExtractTemporaryFile('version_bk.png');
    ExtractTemporaryFile('messagebox_bk.png');
    ExtractTemporaryFile('messagebox_bk_1.png');
    ExtractTemporaryFile('btn_more_options_open.png');
    ExtractTemporaryFile('btn_more_options_open_1.png');
    ExtractTemporaryFile('btn_more_options_close.png');
    ExtractTemporaryFile('btn_more_options_close_1.png');
    ExtractTemporaryFile('button_browse.png');
    ExtractTemporaryFile('button_browse_1.png');
    ExtractTemporaryFile('progressbar_background.png');
    ExtractTemporaryFile('progressbar_foreground.png');
    ExtractTemporaryFile('checkbox_license.png');
    ExtractTemporaryFile('button_cancel.png');
    ExtractTemporaryFile('button_ok.png');
    ExtractTemporaryFile('button_yes.png');
    ExtractTemporaryFile('button_no.png');
    ExtractTemporaryFile('button_continue.png');
    ExtractTemporaryFile('button_teminate.png');
    ExtractTemporaryFile('install_path_edit_bg.png');
    ExtractTemporaryFile('main_win_bg.png');
    ExtractTemporaryFile('dig_btn_solice.png');
    ExtractTemporaryFile('dig_btn_hollow.png');
END;

// 磁盘控件相关
procedure TconSetVisible(lbl:TControl; bVis:BOOLEAN);
begin
    if bVis then
    begin
        lbl.Show;
    end
    else
    begin
        lbl.Hide;
    end;
end;

// check path
function PathCharLength(const S: String; const Index: Integer): Integer;
{ Returns the length in bytes of the character at Index in S.
  Notes:
  1. If Index specifies the last character in S, 1 will always be returned,
     even if the last character is a lead byte.
  2. If a lead byte is followed by a null character (e.g. #131#0), 2 will be
     returned. This mimics the behavior of MultiByteToWideChar and CharPrev,
     but not CharNext(P)-P, which would stop on the null. }
begin
    {$IFNDEF UNICODE}
    if IsDBCSLeadByte(Ord(S[Index])) and (Index < Length(S)) then
        Result := 2
    else
        {$ENDIF}
        Result := 1;
end;

function PathNormalizeSlashes(const S: String): String;
{ Returns S minus any superfluous slashes, and with any forward slashes
  converted to backslashes. For example, if S is 'C:\\\some//path', it returns
  'C:\some\path'. Does not remove a double backslash at the beginning of the
  string, since that signifies a UNC path. }
var
    Len, temp, number, index: Integer;
begin
    Result := S;
    Len := Length(Result);
    index := 1;
    while index <= Len do
    begin
        if Result[index] = '/' then
            Result[index] := '\';
            number := PathCharLength(Result, index);
            temp := index;
            index := temp + number;
    end;
    index := 1;
    while index < Length(Result) do
    begin
        if (Result[index] = '\') and (Result[index+1] = '\') and (index > 1) then
            Delete(Result, index+1, 1)
        else
            number := PathCharLength(Result, index);
            temp := index;
            index := temp + number;
    end;
end;

procedure TidyUpDirName(var Path: String);
{ Tidies up a directory name }
begin
    { Trim spaces, normalize slashes, remove any trailing backslash, then repeat
      the process if necessary (e.g. in the 'C:\Program Files\My Program\ \' case) }
    repeat
        Path := RemoveBackslashUnlessRoot(PathNormalizeSlashes(Trim(Path)));
    until Length(Path) = Length(Trim(Path));
end;

type
    TSysCharSet = set of AnsiChar;
function CharInSet(C: AnsiChar; const CharSet: TSysCharSet): Boolean;
begin
    Result := C in CharSet;
end;

function ValidateCustomDirEdit(const inputPath: String): Boolean;
{ Checks if AEdit.Text contains a valid-looking pathname, and returns True
    if so. May alter AEdit.Text to remove redundant spaces and backslashes. }
var
    IsUNCPath: Boolean;
    driveType: Integer;
begin
    Result := False;
    TidyUpDirName(inputPath);

    { Check if the path is too long.
        Note: There's no sense in allowing paths to be as long as MAX_PATH (260)
        since there wouldn't be any room left to append a filename. 240 should be
        a reasonable limit. }
    if Length(inputPath) > 240 then
    begin
        Exit;
    end;

    { Check for UNC pathname }
    IsUNCPath := (Length(inputPath) >= 2) and (inputPath[1] = '\') and (inputPath[2] = '\');
    if IsUNCPath then
    begin
        Exit;
    end;

    if(PathIsNetworkPath(inputPath)) then
    begin
        EXIT;
    end;

    driveType := GetDriveType(inputPath);
    if (driveType = 2) or (driveType = 4) then
    begin
        Exit;
    end;
    Result := True;
end;

function Misc_FomatByteText(const I: Int64):string;
var
    X: Extended;
begin
    if I > 1073741824 then
    begin
        X := (I*1.0 / 1073741824) * 100;
        X := X / 100;
        Result := Format('%.2f GB', [X]);
        Exit;
    end;

    if I > 1048576 then
    begin
        X := (I*1.0 / 1048576) * 10;
        X := X / 10;
        Result := Format('%.1f MB', [X]);
        Exit;
    end;

    if I > 1024 then
    begin
        X := I*1.0 / 1024;
        Result := Format('%.0f KB', [X]);
        Exit;
    end;
    Result := Format('%d B', [I]);
end;

function GetNeedSpaceText():string;
var
    iv:string;
begin
    iv:= Misc_FomatByteText(dNeedSpaceByte);
    result := ExpandConstant('{cm:install_path_required}') + format(' %s', [iv]);
end;

function GetCurDirFreeSpace():Cardinal;
var
    curPath:string;
    FreeSpace,TotalSpace:Cardinal;
begin
    curPath := edit_target_path.Text;
    GetSpaceOnDisk(ExtractFileDrive(curPath),True,FreeSpace,TotalSpace);
    result := FreeSpace;
end;

function GetDiskSpaceText(FreeSpace:Cardinal): string;
var
    iv: string;
begin
    if FreeSpace > 1024 then
    begin
        iv := Format('%.0f GB',[FreeSpace/1024.0 ]) ;
    end
    else
    begin
        iv := Format('%d MB',[FreeSpace]);
    end;
    result := ExpandConstant('{cm:available}') + format(' %s',[iv]);
end;

procedure WhenInstallDirChangeCheckDiskSpace();
var FreeSpace: Cardinal;
    errorDir: AnsiString;
    driveType: Integer;
begin
    FreeSpace := GetCurDirFreeSpace();
    label_need_space.Caption := GetNeedSpaceText();
    label_disk_space.Caption := GetDiskSpaceText(FreeSpace);
    driveType := GetDriveType(edit_target_path.Text);

    if not ValidateCustomDirEdit(edit_target_path.Text) then
    begin
        label_warn_tips.Caption := ExpandConstant('{cm:tipii}')
        TconSetVisible(label_warn_tips, TRUE);
        BtnSetEnabled(button_install_now, FALSE);
        Exit;
    end;

    if (FreeSpace <= (dNeedSpaceByte / 1024 / 1024)) then
    begin
        label_warn_tips.Caption := ExpandConstant('{cm:tdssi}')
        TconSetVisible(label_warn_tips, TRUE);
        BtnSetEnabled(button_install_now, FALSE);
        Exit;
    end;
        label_warn_tips.Caption := ''
        TconSetVisible(label_warn_tips, FALSE);
    if BtnGetChecked(checkbox_license) then
    begin
        BtnSetEnabled(button_install_now, TRUE);
    end
    else
    begin
        BtnSetEnabled(button_install_now, FALSE);
    end;
end;

//主界面浏览按钮按下时执行的脚本
PROCEDURE button_browse_on_click(hBtn : HWND);
BEGIN
    WizardForm.DirBrowseButton.OnClick(WizardForm);
    edit_target_path.Text := WizardForm.DirEdit.Text;
    WhenInstallDirChangeCheckDiskSpace();
END;

//路径输入框文本变化时执行的脚本
PROCEDURE edit_target_path_on_change(Sender : TObject);
BEGIN
    WizardForm.DirEdit.Text := edit_target_path.Text;
    WhenInstallDirChangeCheckDiskSpace();
END;

//主界面关闭按钮按下时执行的脚本
PROCEDURE button_close_on_click(hBtn : HWND);
BEGIN
    WizardForm.CancelButton.OnClick(WizardForm);
END;

//主界面最小化按钮按下时执行的脚本
PROCEDURE button_minimize_on_click(hBtn : HWND);
BEGIN
    SendMessage(WizardForm.Handle, WM_SYSCOMMAND, 61472, 0);
END;

//主界面自定义安装按钮按下时执行的脚本
PROCEDURE btn_more_options_on_click(hBtn : HWND);   //hBtn : HWND
BEGIN
    IF is_wizardform_show_normal THEN
    BEGIN
        WhenInstallDirChangeCheckDiskSpace();
        mainBkPanel.Height := WIZARDFORM_HEIGHT_MORE - WIZARDFORM_BORDER_WIDTH * 2;
        WizardForm.Height := WIZARDFORM_HEIGHT_MORE;
        edit_target_path.Show();
        BtnSetVisibility(button_browse, TRUE);
        BtnSetVisibility(btn_more_options, FALSE);
        BtnSetVisibility(btn_more_options_close, TRUE);
        is_wizardform_show_normal := FALSE;
    END ELSE
    BEGIN
        edit_target_path.Hide();
        label_error_tips.Hide();
        BtnSetVisibility(button_browse, FALSE);
        mainBkPanel.Height := WIZARDFORM_HEIGHT_NORMAL - WIZARDFORM_BORDER_WIDTH * 2;
        WizardForm.Height := WIZARDFORM_HEIGHT_NORMAL;
        BtnSetVisibility(btn_more_options, TRUE);
        BtnSetVisibility(btn_more_options_close, FALSE);
        is_wizardform_show_normal := TRUE;
    END;
    ImgApplyChanges(mainBkPanel.Handle);
    ImgApplyChanges(WizardForm.Handle);
END;

//同意许可协议的复选框被点击时执行的脚本
PROCEDURE checkbox_license_on_click(hBtn : HWND);
BEGIN
    if BtnGetChecked(checkbox_license) and not label_warn_tips.Visible then
    begin
        BtnSetEnabled(button_install_now, TRUE);
    end else
    begin
        BtnSetEnabled(button_install_now, FALSE);
    end;
END;

//释放安装程序时调用的脚本
PROCEDURE release_installer();
BEGIN
    gdipShutdown();
    messagebox_close.Release();
    WizardForm.Release();
END;

function IsAppRunning(FileName : string): Boolean;
var
    FSWbemLocator: Variant;
    FWMIService: Variant;
    FWbemObjectSet: Variant;
begin
    Result := false;
    FSWbemLocator := CreateOleObject('WBEMScripting.SWBEMLocator');
    FWMIService := FSWbemLocator.ConnectServer('', 'root\CIMV2', '', '');
    FWbemObjectSet := FWMIService.ExecQuery(Format('SELECT Name FROM Win32_Process Where Name="%s"',[FileName]));
    Result := (FWbemObjectSet.Count > 0);
    FWbemObjectSet := Unassigned;
    FWMIService := Unassigned;
    FSWbemLocator := Unassigned;
end;

function DirExists(const Name: String): Boolean;
{   Returns True if the specified directory name exists. The specified name
    may include a trailing backslash.
    NOTE: Delphi's FileCtrl unit has a similar function called DirectoryExists.
    However, the implementation is different between Delphi 1 and 2. (Delphi 1
    does not count hidden or system directories as existing.) }
var
    Attr: Integer;
begin
    Attr := GetFileAttributes(Name);
    Result := (Attr <> -1) and (Attr and 16 <> 0);
end;


//messagebox pop 1:close program 2:install path exists 3.program have install 4.app is running
PROCEDURE MessageboxShowModal(msgType: INTEGER);
BEGIN
    IF (msgType = 1) THEN
    BEGIN
        label_messagebox_information.Caption := ExpandConstant('{cm:siapwn}')
        if 'cn' = language then
        begin
            label_messagebox_information.Left := 150;
            label_messagebox_information.Top := 24;
            label_messagebox_information.Width := 120;
            label_messagebox_information.Height := 70;
        end
        else
        begin
            label_messagebox_information.Left := 60;
            label_messagebox_information.Top := 24;
            label_messagebox_information.Width := 300;
            label_messagebox_information.Height := 70;
        end;
        BtnSetVisibility(button_messagebox_continue, TRUE);
        BtnSetVisibility(button_messagebox_teminate, TRUE);
        BtnSetVisibility(button_messagebox_ok, FALSE);
        BtnSetVisibility(button_messagebox_yes, FALSE);
        BtnSetVisibility(button_messagebox_no, FALSE);
    END ELSE IF (msgType = 2) THEN
    BEGIN
        label_messagebox_information.Caption := ExpandConstant('{cm:tipaey}')
        if 'cn' = language then
        begin
            label_messagebox_information.Left := 130;
            label_messagebox_information.Top := 24;
            label_messagebox_information.Width := 260;
            label_messagebox_information.Height := 70;
        end
        else
        begin
            label_messagebox_information.Left := 20;
            label_messagebox_information.Top := 24;
            label_messagebox_information.Width := 360;
            label_messagebox_information.Height := 70;
        end;
        BtnSetVisibility(button_messagebox_continue, FALSE);
        BtnSetVisibility(button_messagebox_teminate, FALSE);
        BtnSetVisibility(button_messagebox_ok, FALSE);
        BtnSetVisibility(button_messagebox_yes, TRUE);
        BtnSetVisibility(button_messagebox_no, TRUE);
    END ELSE IF (msgType = 3) THEN
    BEGIN
        label_messagebox_information.Caption := ExpandConstant('{cm:yiapwi}')
        if 'cn' = language then
        begin
            label_messagebox_information.Left := 130;
            label_messagebox_information.Top := 24;
            label_messagebox_information.Width := 140;
            label_messagebox_information.Height := 70;
        end
        else
        begin
            label_messagebox_information.Left := 20;
            label_messagebox_information.Top := 24;
            label_messagebox_information.Width := 360;
            label_messagebox_information.Height := 70;
        end;
        BtnSetVisibility(button_messagebox_continue, FALSE);
        BtnSetVisibility(button_messagebox_teminate, FALSE);
        BtnSetVisibility(button_messagebox_ok, FALSE);
        BtnSetVisibility(button_messagebox_yes, TRUE);
        BtnSetVisibility(button_messagebox_no, TRUE);
    END ELSE IF (msgType = 4) THEN
    BEGIN
        label_messagebox_information.Caption := ExpandConstant('{cm:yuapwp}')
        if 'cn' = language then
        begin
            label_messagebox_information.Left := 90;
            label_messagebox_information.Top := 24;
            label_messagebox_information.Width := 250;
            label_messagebox_information.Height := 70;
        end
        else
        begin
            label_messagebox_information.Left := 20;
            label_messagebox_information.Top := 24;
            label_messagebox_information.Width := 360;
            label_messagebox_information.Height := 70;
        end;
        BtnSetVisibility(button_messagebox_continue, FALSE);
        BtnSetVisibility(button_messagebox_teminate, FALSE);
        BtnSetVisibility(button_messagebox_ok, TRUE);
        BtnSetVisibility(button_messagebox_yes, FALSE);
        BtnSetVisibility(button_messagebox_no, FALSE);
    END;
    messagebox_close.Left := WizardForm.Left + (WizardForm.width - messagebox_close.width) div 2;
    messagebox_close.top := WizardForm.Top + (WizardForm.height - messagebox_close.height) div 2;
    messagebox_close.ShowModal();
END;

//主界面安装按钮按下时执行的脚本
PROCEDURE install_right_now_on_click(hBtn : HWND);
var
    resultCode: Boolean;
    uicmd:String;
BEGIN
    resultCode := IsAppRunning(ExpandConstant('{#MyAppExeName}'));
    if resultCode then
    begin
        MessageboxShowModal(4)
    end
    else
        if RegQueryStringValue(HKEY_LOCAL_MACHINE, PRODUCT_REGISTRY_KEY, 'UninstallString', uicmd) then
        begin
            MessageboxShowModal(3)
            if(can_next_setup) then
            begin
                WizardForm.NextButton.OnClick(WizardForm);
            end;
        end
        else
            if DirExists(WizardForm.DirEdit.Text) then
            begin
                MessageboxShowModal(2)
                if(can_next_setup) then
                begin
                    WizardForm.NextButton.OnClick(WizardForm);
                end;
            end
            else
            begin
                WizardForm.NextButton.OnClick(WizardForm);
            end;
END;

//重载主界面取消按钮被按下后的处理过程
PROCEDURE CancelButtonClick(CurPageID : INTEGER; VAR Cancel, Confirm: BOOLEAN);
BEGIN
    Confirm := FALSE;
    if b_auto_install then
    begin MessageboxShowModal(4); end
    else
    begin MessageboxShowModal(1); end;
    IF can_exit_setup THEN
    BEGIN
        Cancel := TRUE;
    END ELSE
    BEGIN
        Cancel := FALSE;
    END;
END;

PROCEDURE button_messagebox_ok_on_click(hBtn : HWND);
BEGIN
    messagebox_close.Close();
    WizardForm.Close();
    can_exit_setup := True;
END;

PROCEDURE button_messagebox_yes_on_click(hBtn : HWND);
BEGIN
    messagebox_close.Close();
    can_next_setup := True;
END;

PROCEDURE button_messagebox_no_on_click(hBtn : HWND);
BEGIN
    messagebox_close.Close();
    can_next_setup := False;
END;

PROCEDURE button_messagebox_continue_on_click(hBtn : HWND);
BEGIN
    messagebox_close.Close();
    can_exit_setup := False;
END;

PROCEDURE button_messagebox_teminate_on_click(hBtn : HWND);
BEGIN
    messagebox_close.Close();
    WizardForm.Close();
    can_exit_setup := True;
END;

//立即运行
PROCEDURE run_now_on_click(hBtn : HWND);
BEGIN
    WizardForm.NextButton.OnClick(WizardForm);
END;

//复制文件时执行的脚本，每复制1%都会被调用一次，若要调整进度条或进度提示请在此段修改
FUNCTION PBProc(h : hWnd; Msg, wParam, lParam : LONGINT) : LONGINT;
VAR
    pr, i1, i2 : EXTENDED;
    w : INTEGER;
    tipStr: String;
BEGIN
    Result := CallWindowProc(PBOldProc, h, Msg, wParam, lParam);
    IF ((Msg = $402) AND (WizardForm.ProgressGauge.Position > WizardForm.ProgressGauge.Min)) THEN
    BEGIN
        i1 := WizardForm.ProgressGauge.Position - WizardForm.ProgressGauge.Min;
        i2 := WizardForm.ProgressGauge.Max - WizardForm.ProgressGauge.Min;
        pr := (i1 * 100) / i2;
        if b_auto_install then
        begin tipStr := ExpandConstant('{cm:upta}'); end
        else begin tipStr := ExpandConstant('{cm:installing}'); end;
        label_install_progress.Caption := tipStr + Format(' %d', [Round(pr)]) + '%';
        w := Round((550 * pr) / 100);
        ImgSetPosition(image_progressbar_foreground, 55, 315, w, 4);
        ImgSetVisiblePart(image_progressbar_foreground, 0, 0, w, 4);
        ImgApplyChanges(mainBkPanel.Handle);
    END;
END;

//阅读许可协议的按钮按下时执行的脚本
PROCEDURE button_license_on_click(Sender : TObject; Button : TMouseButton; Shift : TShiftState; X, Y : INTEGER);
VAR
    ErrorCode : INTEGER;
BEGIN
    ReleaseCapture();
    ShellExec('', '{#MyAppLicenseURL}', '', '', SW_SHOW, ewNoWait, ErrorCode);
END;

//安装失败的官网链接
PROCEDURE button_anycubic_website_on_click(Sender : TObject; Button : TMouseButton; Shift : TShiftState; X, Y : INTEGER);
VAR
    ErrorCode : INTEGER;
BEGIN
    ReleaseCapture();
    ShellExec('', '{#AnycubicWebsiteURL}', '', '', SW_SHOW, ewNoWait, ErrorCode);
END;

//取消安装弹框的取消按钮按下时执行的脚本
PROCEDURE button_messagebox_cancel_on_click(hBtn : HWND);
BEGIN
    messagebox_close.Close();
END;

//主界面被点住就随鼠标移动的脚本
PROCEDURE wizardform_on_mouse_down(Sender : TObject; Button : TMouseButton; Shift : TShiftState; X, Y : INTEGER);
BEGIN
    ReleaseCapture();
    SendMessage(WizardForm.Handle, WM_SYSCOMMAND, $F012, 0);
END;

//取消弹框被点住就随鼠标移动的脚本
PROCEDURE messagebox_on_mouse_down(Sender : TObject; Button : TMouseButton; Shift : TShiftState; X, Y : INTEGER);
BEGIN
  ReleaseCapture();
  SendMessage(messagebox_close.Handle, WM_SYSCOMMAND, $F012, 0);
END;

//判断系统是否为Win7，是则返回TRUE，否则返回FALSE
PROCEDURE determine_wether_is_windows_7_or_not();
VAR
  sysVersion : TWindowsVersion;
BEGIN
    GetWindowsVersionEx(sysVersion);
    IF sysVersion.NTPlatform AND (sysVersion.Major = 6) AND (sysVersion.Minor = 1) THEN
    BEGIN
        is_platform_windows_7 := TRUE;
    END ELSE
    BEGIN
        is_platform_windows_7 := FALSE;
    END;
END;

//创建取消弹框的脚本
PROCEDURE messagebox_close_create();
BEGIN
    messagebox_close := CreateCustomForm();
    WITH messagebox_close DO
    BEGIN
        BorderStyle := bsNone;
        Width := 400;
        Height := 154;
        Left := WizardForm.Left + (WizardForm.width - messagebox_close.width) div 2;
        Top := WizardForm.Top + (WizardForm.height - messagebox_close.height) div 2;
        Color := $FCD6BD;
        ImgLoad(messagebox_close.Handle, ExpandConstant('{tmp}\messagebox_bk_1.png'), 0, 0, 400, 154, FALSE, TRUE);
        ImgApplyChanges(messagebox_close.Handle);
    END;

    label_messagebox_information := TLabel.Create(messagebox_close);
    WITH label_messagebox_information DO
    BEGIN
        Parent := messagebox_close;
        AutoSize := FALSE;
        Left := 20;
        Top := 24;
        Width := 360;
        Height := 70;
        Font.Name := 'Arial';
        Font.Size := 10;
        Font.Color := $333333;
        Transparent := TRUE;
        WordWrap := TRUE;
        OnMouseDown := @messagebox_on_mouse_down;
    END;
        label_messagebox_main := TLabel.Create(messagebox_close);
    WITH label_messagebox_main DO
    BEGIN
        Parent := messagebox_close;
        AutoSize := FALSE;
        Left := 0;
        Top := 0;
        Width := messagebox_close.Width;
        Height := messagebox_close.Height;
        Transparent := TRUE;
        OnMouseDown := @messagebox_on_mouse_down;
    END;

    //btn ok
    button_messagebox_ok := BtnCreate(messagebox_close.Handle, 152, 102, 96, 28, ExpandConstant('{tmp}\dig_btn_solice.png'), 0, FALSE);
    BtnSetText(button_messagebox_ok, ExpandConstant('{cm:ok}'));//按钮文字
    //文字字体
    button_messagebox_ok_font := TFont.Create;
    with button_messagebox_ok_font do
    begin
        Size := 9;
        Name := 'Arial';
        Color := $FFFFFF;
    end;
    //应用字体
    BtnSetFont(button_messagebox_ok, button_messagebox_ok_font.Handle);
    BtnSetFontColor(button_messagebox_ok, $FFFFFF, $FFFFFF, $FFFFFF, $FFFFFF);
    BtnSetEvent(button_messagebox_ok, ID_BUTTON_ON_CLICK_EVENT, WrapBtnCallback(@button_messagebox_ok_on_click, 1));
    BtnSetVisibility(button_messagebox_ok, FALSE);

    //btn yes
    button_messagebox_yes := BtnCreate(messagebox_close.Handle, 96, 102, 96, 28, ExpandConstant('{tmp}\dig_btn_solice.png'), 0, FALSE);
    BtnSetText(button_messagebox_yes, ExpandConstant('{cm:yes}'));//按钮文字
    //文字字体
    button_messagebox_yes_font := TFont.Create;
    with button_messagebox_yes_font do
    begin
        Size := 9;
        Name := 'Arial';
        Color := $FFFFFF;
    end;
    //应用字体
    BtnSetFont(button_messagebox_yes, button_messagebox_yes_font.Handle);
    BtnSetFontColor(button_messagebox_yes, $FFFFFF, $FFFFFF, $FFFFFF, $FFFFFF);
    BtnSetEvent(button_messagebox_yes, ID_BUTTON_ON_CLICK_EVENT, WrapBtnCallback(@button_messagebox_yes_on_click, 1));
    BtnSetVisibility(button_messagebox_yes, FALSE);

    //btn no
    button_messagebox_no := BtnCreate(messagebox_close.Handle, 208, 102, 96, 28, ExpandConstant('{tmp}\dig_btn_hollow.png'), 0, FALSE);
    BtnSetText(button_messagebox_no, ExpandConstant('{cm:no}'));//按钮文字
    //文字字体
    button_messagebox_no_font := TFont.Create;
    with button_messagebox_no_font do
    begin
        Size := 9;
        Name := 'Arial';
        Color := $FF8639;
    end;
    //应用字体
    BtnSetFont(button_messagebox_no, button_messagebox_no_font.Handle);
    BtnSetFontColor(button_messagebox_no, $FF8639, $FFB080, $E0691D, $FCD6BD);
    BtnSetEvent(button_messagebox_no, ID_BUTTON_ON_CLICK_EVENT, WrapBtnCallback(@button_messagebox_no_on_click, 1));
    BtnSetVisibility(button_messagebox_no, FALSE);

    //btn continue
    button_messagebox_continue := BtnCreate(messagebox_close.Handle, 96, 102, 96, 28, ExpandConstant('{tmp}\dig_btn_solice.png'), 0, FALSE);
    BtnSetText(button_messagebox_continue, ExpandConstant('{cm:continue}'));//按钮文字
    //文字字体
    button_messagebox_continue_font := TFont.Create;
    with button_messagebox_continue_font do
    begin
        Size := 9;
        Name := 'Arial';
        Color := $FFFFFF;
    end;
    //应用字体
    BtnSetFont(button_messagebox_continue, button_messagebox_continue_font.Handle);
    BtnSetFontColor(button_messagebox_continue, $FFFFFF, $FFFFFF, $FFFFFF, $FFFFFF);
    BtnSetEvent(button_messagebox_continue, ID_BUTTON_ON_CLICK_EVENT, WrapBtnCallback(@button_messagebox_continue_on_click, 1));
    BtnSetVisibility(button_messagebox_continue, FALSE);

    //btn teminate
    button_messagebox_teminate := BtnCreate(messagebox_close.Handle, 208, 102, 96, 28, ExpandConstant('{tmp}\dig_btn_hollow.png'), 0, FALSE);
    BtnSetText(button_messagebox_teminate, ExpandConstant('{cm:teminate}'));//按钮文字
    //文字字体
    button_messagebox_teminate_font := TFont.Create;
    with button_messagebox_teminate_font do
    begin
        Size := 9;
        Name := 'Arial';
        Color := $FF8639;
    end;
    //应用字体
    BtnSetFont(button_messagebox_teminate, button_messagebox_teminate_font.Handle);
    BtnSetFontColor(button_messagebox_teminate, $FF8639, $FFB080, $E0691D, $FCD6BD);
    BtnSetEvent(button_messagebox_teminate, ID_BUTTON_ON_CLICK_EVENT, WrapBtnCallback(@button_messagebox_teminate_on_click, 1));
    BtnSetVisibility(button_messagebox_teminate, FALSE);

    //button_messagebox_cancel := BtnCreate(messagebox_close.Handle, 293, 150, 76, 28, ExpandConstant('{tmp}\button_cancel.png'), 0, FALSE);
    //BtnSetEvent(button_messagebox_cancel, ID_BUTTON_ON_CLICK_EVENT, WrapBtnCallback(@button_messagebox_cancel_on_click, 1));
    //BtnSetVisibility(button_messagebox_cancel, FALSE);
    //SetWindowLong(messagebox_close.Handle, GCL_STYLE, GetClassLong(messagebox_close.Handle, GCL_STYLE) or CS_DROPSHADOW);
END;

// 初始化UI变量
procedure InitData();
begin
    isFirst := TRUE;
    is_installer_initialized := TRUE;
    is_wizardform_show_normal := TRUE;
    is_wizardform_released := FALSE;
    determine_wether_is_windows_7_or_not();
    extract_temp_files();
    WizardForm.InnerNotebook.Hide();
    WizardForm.OuterNotebook.Hide();
    WizardForm.Bevel.Hide();
    dNeedSpaceByte := {#MyAppNeedSpaceByte}
end;

// 初始化UI变量
procedure InitUI();
var
    temp1, temp2: String;
    Version1, Version2, Version3: String;
    pathEditTipOffset: Integer;
    checkbox_license_left: Integer;
    checkbox_license_top: Integer;
    label_need_space_left_offset: Integer;
    btn_more_options_right_offset: String;
    tipStr: String;
BEGIN
    // 初始化主窗口背景 ------------>
    with WizardForm do
    begin
        BorderStyle := bsNone;
        Position := poScreenCenter;
        Width := WIZARDFORM_WIDTH_NORMAL;
        Height := WIZARDFORM_HEIGHT_NORMAL//WIZARDFORM_HEIGHT_MORE;
        Color := $FCD6BD;
        NextButton.Height := 0;
        CancelButton.Height := 0;
        BackButton.Visible := FALSE;
    end;

    mainBkPanel := TPanel.Create(WizardForm); //背景贴图
    with mainBkPanel do
    begin
        Parent := WizardForm;
        Top := WIZARDFORM_BORDER_WIDTH;
        Left := WIZARDFORM_BORDER_WIDTH;
        BorderStyle := bsNone
        Width := WIZARDFORM_WIDTH_NORMAL - WIZARDFORM_BORDER_WIDTH * 2;
        Height := WIZARDFORM_HEIGHT_MORE - WIZARDFORM_BORDER_WIDTH * 2;
        BevelKind := bkNone;
        BevelInner := bvNone;
        BevelOuter := bvNone;
        Visible := True;
    end;
    image_wizardform_background := ImgLoad(mainBkPanel.Handle, ExpandConstant('{tmp}\main_win_bg.png'), 0, 0, WIZARDFORM_WIDTH_NORMAL, WIZARDFORM_HEIGHT_MORE, FALSE, TRUE);
    ImgApplyChanges(mainBkPanel.Handle);
    ImgApplyChanges(WizardForm.Handle);

    label_wizardform_main := TLabel.Create(mainBkPanel);// 主窗口可拖动标题栏大小
    with label_wizardform_main do
    begin
        Parent := mainBkPanel;
        AutoSize := FALSE;
        Left := 0;
        Top := 0;
        Width := mainBkPanel.Width;
        Height := MAIN_WIN_MOUSE_DRAGGABLE_HEIGHT;
        Transparent := TRUE;
        OnMouseDown := @wizardform_on_mouse_down;
    end;
    //<--------------------------------------------

    // 主界面最大化和最小化按钮 ----------------->
    button_close := BtnCreate(mainBkPanel.Handle, 629, 3, 28, 28, ExpandConstant('{tmp}\button_close.png'), 0, FALSE);
    BtnSetEvent(button_close, ID_BUTTON_ON_CLICK_EVENT, WrapBtnCallback(@button_close_on_click, 1));
    button_minimize := BtnCreate(mainBkPanel.Handle, 591, 3, 28, 28, ExpandConstant('{tmp}\button_minimize.png'), 0, FALSE);
    BtnSetEvent(button_minimize, ID_BUTTON_ON_CLICK_EVENT, WrapBtnCallback(@button_minimize_on_click, 1));
    //<----------------------------------------------

    //软件标题---------------------->app_name_label app_name_font
    app_name_label := TLabel.Create(mainBkPanel);
    with app_name_label do
    begin
        Parent:= mainBkPanel;
        AutoSize:= TRUE;
        Caption:= ExpandConstant('{cm:app_name}');
        Transparent:= TRUE;
        Font.Size:= 24
        Font.Name:= 'Arial'
        Font.Color:= $291C14
        Left := (mainBkPanel.Width - Width) div 2;
        Top := (mainBkPanel.Height - Height) div 2 - 60;
    end;
    //<----------------------------------------------

    // 版本显示标签  ---------->
    image_version_background := ImgLoad(mainBkPanel.Handle, ExpandConstant('{tmp}\version_bk.png'), app_name_label.Left + app_name_label.Width + 4, app_name_label.Top, 41, 19, TRUE, TRUE);
    label_version := TLabel.Create(mainBkPanel);
    temp1 := '{#MyAppVersion}';
    Version1 := Copy(temp1, 1, Pos('.', temp1) - 1);
    temp1 := Copy(temp1, Pos('.', temp1) + 1, Length(temp1));
    Version2 := Copy(temp1, 1, Pos('.', temp1) - 1);
    temp1 := Copy(temp1, Pos('.', temp1) + 1, Length(temp1));
    Version3 := Copy(temp1, 1, Pos('.', temp1) - 1);
    temp2 := Version1 + '.' + Version2 + '.' + Version3
    with label_version do
    begin
        Parent := mainBkPanel;
        AutoSize := TRUE;
        Caption := temp2;
        Transparent := true;
        Font.Size:= 9
        Font.Name:='Arial'
        Font.Color:=$FFFFFF
        Left := app_name_label.Left + app_name_label.Width + 4 + 6;
        Top := app_name_label.Top + 2;
        Width := 41;
        Height := 19;
    end;
    //<------------------------------------------------


    // 立即安装按钮自定义 ---->
    button_install_now := BtnCreate(mainBkPanel.Handle, (mainBkPanel.Width - 214) div 2, app_name_label.Top + app_name_label.Height + 60, 214, 51, ExpandConstant('{tmp}\install_right_now_1.png'), 0, FALSE);
    BtnSetText(button_install_now, ExpandConstant('{cm:install_name}'));//按钮文字
    //文字字体
    button_install_now_font := TFont.Create;
    with button_install_now_font do
    begin
        Size := 18;
        Name := 'Arial';
        Color := $FF8639;
        Style := [fsBold];
    end;
    //应用字体
    BtnSetFont(button_install_now, button_install_now_font.Handle);
    BtnSetFontColor(button_install_now, $FF8639, $FFB080, $E0691D, $FCD6BD);
    BtnSetEvent(button_install_now, ID_BUTTON_ON_CLICK_EVENT, WrapBtnCallback(@install_right_now_on_click, 1));
    BtnSetEnabled(button_install_now, FALSE);
    BtnSetVisibility(button_install_now, FALSE);
    //<------------------------------------------------------------


    // 许可证复选框  --------->
    checkbox_license_left := 240;
    if 'cn' = language then
    begin
        checkbox_license_left := 250;
    end
    else
    begin
        checkbox_license_left := 117;
    end;
    checkbox_license_top := app_name_label.Top + app_name_label.Height + 140;
    checkbox_license := BtnCreate(mainBkPanel.Handle, checkbox_license_left, checkbox_license_top, 16, 16, ExpandConstant('{tmp}\checkbox_license.png'), 0, TRUE);
    BtnSetEvent(checkbox_license, ID_BUTTON_ON_CLICK_EVENT, WrapBtnCallback(@checkbox_license_on_click, 1));
    BtnSetChecked(checkbox_license, FALSE);
    BtnSetVisibility(checkbox_license, FALSE);
    // 阅读和同意title
    label_agree_title := TLabel.Create(mainBkPanel);
    with label_agree_title do
    begin
        Parent := mainBkPanel;
        AutoSize := TRUE;
        Left := checkbox_license_left + 16 + 6;
        Top := checkbox_license_top;
        Caption := ExpandConstant('{cm:ihraat}');
        Font.Name := 'Arial';
        Font.Size := 12;
        Font.Color := $291c14;
        Transparent := TRUE;
        Hide();
    end;

    // 条款
    label_agree_content := TLabel.Create(mainBkPanel);
    with label_agree_content do
    begin
        Parent := mainBkPanel;
        AutoSize := TRUE;
        Left := label_agree_title.Left + label_agree_title.Width;
        Top := label_agree_title.Top;
        Caption := ExpandConstant('{cm:tula}');;
        Font.Name := 'Arial';
        Font.Size := 12;
        Font.Color := $FF8639;
        Transparent := TRUE;
        OnMouseDown := @button_license_on_click;
        Cursor := crHand;
        Hide();
    end;
    //<----------------------------------------------------


    // 更多选择下拉选项 -- 展开 ------>
    if 'en' = language then
    begin
        btn_more_options_right_offset := ' ';
    end;
    btn_more_options := BtnCreate(mainBkPanel.Handle, (mainBkPanel.Width - 144) div 2 - 16, app_name_label.Top + app_name_label.Height + 180, 144, 21, ExpandConstant('{tmp}\btn_more_options_close_1.png'), 0, FALSE);
    BtnSetText(btn_more_options, ExpandConstant('{cm:more_options}') + btn_more_options_right_offset);//按钮文字
    //文字字体
    btn_more_options_font := TFont.Create;
    with btn_more_options_font do begin
        Size := 12;
        Name := 'Arial';
        Color := $808080;
    end;
    //应用字体
    BtnSetFont(btn_more_options, btn_more_options_font.Handle);
    BtnSetFontColor(btn_more_options, $808080, $FFB080, $FF8639, $D2D2D2);
    BtnSetEvent(btn_more_options, ID_BUTTON_ON_CLICK_EVENT, WrapBtnCallback(@btn_more_options_on_click, 1));
    BtnSetVisibility(btn_more_options, FALSE);
    //<--------------------------------------------------

    // 更多选择下拉选项 -- 关闭 ------>btn_more_options_font_1
    btn_more_options_close := BtnCreate(mainBkPanel.Handle, (mainBkPanel.Width - 144) div 2 - 16, app_name_label.Top + app_name_label.Height + 180, 144, 21, ExpandConstant('{tmp}\btn_more_options_open_1.png'), 0, FALSE);
    BtnSetText(btn_more_options_close, ExpandConstant('{cm:more_options}') + btn_more_options_right_offset);//按钮文字
    //文字字体
    btn_more_options_font_1 := TFont.Create;
    with btn_more_options_font_1 do begin
        Size := 12;
        Name := 'Arial';
        Color := $808080;
    end;
    //应用字体
    BtnSetFont(btn_more_options_close, btn_more_options_font_1.Handle);
    BtnSetFontColor(btn_more_options_close, $808080, $FFB080, $FF8639, $D2D2D2);
    BtnSetEvent(btn_more_options_close, ID_BUTTON_ON_CLICK_EVENT, WrapBtnCallback(@btn_more_options_on_click, 1));
    BtnSetVisibility(btn_more_options_close, FALSE);
    //<----------------------------------------------------

    // 路径设置TEdit控件初始化---------------------->
    pathEditTipOffset := 6
    label_need_space_left_offset := 80
    if 'cn' = language then
    begin
        label_need_space_left_offset := 70
    end
    else
    begin
        label_need_space_left_offset := 90
    end;
    ImgLoad(mainBkPanel.Handle, ExpandConstant('{tmp}\install_path_edit_bg.png'), 40, 520, 450, 38, FALSE, TRUE);
    edit_target_path:= TEdit.Create(mainBkPanel);
    with edit_target_path do
    begin
        Parent := mainBkPanel;
        Text := WizardForm.DirEdit.Text;
        Font.Name := 'Arial';
        Font.Size := 12;
        Font.Color := $291c14;
        BorderStyle := bsNone;
        Color := $FFFFFF;
        TabStop := FALSE;
        OnChange := @edit_target_path_on_change;
        SetBounds(40 + 10, 530, 435, 22);
        Hide();
    end;
    //<------------------------------------------------------------

    // 磁盘空间判断的TLabel  ------------>
    label_need_space := TLabel.Create(mainBkPanel);
    with label_need_space do
    begin
        Parent:= mainBkPanel;
        AutoSize := TRUE;
        Transparent:= true;
        Font.Size:= 11
        Font.Name:= 'Arial'
        Font.Color:= $808080
        Left:= edit_target_path.Left - pathEditTipOffset;
        Top:= edit_target_path.Top - Height - 20;
    end;

    label_disk_space := TLabel.Create(mainBkPanel);
    with label_disk_space do
    begin
        Parent:= mainBkPanel;
        AutoSize := TRUE;
        Transparent:= true;
        Font.Size:= 11
        Font.Name:= 'Arial'
        Font.Color:= $808080
        Left:= edit_target_path.Left + edit_target_path.width - label_need_space_left_offset;
        Top:= edit_target_path.Top - Height - 20;
    end;

    label_warn_tips := TLabel.Create(mainBkPanel);
    with label_warn_tips do
    begin
        Parent:= mainBkPanel;
        AutoSize := TRUE;
        Transparent:= true;
        Font.Size:= 10
        Font.Name:= 'Arial'
        Font.Color:= $4F4DFF
        Left:= edit_target_path.Left - pathEditTipOffset;
        Top:= edit_target_path.Top + Height + 15;
        Hide();
    end;
    //<---------------------------------------------------------

    // 内存等错误tips   --------------->   没有看到显示的地方
    label_error_tips := TLabel.Create(mainBkPanel);
    with label_error_tips do
    begin
        Parent := mainBkPanel;
        AutoSize := FALSE;
        Left := 85;
        Top := 449;
        Width := 200;
        Height := 20;
        Font.Name := 'Arial';
        Font.Size := 9;
        Font.Color := clGray;
        Caption := ExpandConstant('{cm:tshbi}');
        Transparent := TRUE;
        OnMouseDown := @wizardform_on_mouse_down;
        Hide();
    end;
    //< -------------------------------------------------------

    // 进度条-------------------------->
    label_install_progress := TLabel.Create(mainBkPanel);
    WITH label_install_progress DO
    BEGIN
        Parent := mainBkPanel;
        AutoSize := TRUE;
        Font.Name := 'Arial';
        Font.Size := 16;
        Font.Color := $FF8639;
        Transparent := TRUE;
        OnMouseDown := @wizardform_on_mouse_down;
    END;
    PBOldProc := SetWindowLong(WizardForm.ProgressGauge.Handle, -4, PBCallBack(@PBProc, 4));
    image_progressbar_background := ImgLoad(mainBkPanel.Handle, ExpandConstant('{tmp}\progressbar_background.png'), 55, 315, 550, 4, FALSE, TRUE);
    image_progressbar_foreground := ImgLoad(mainBkPanel.Handle, ExpandConstant('{tmp}\progressbar_foreground.png'), 55, 315, 0, 0, TRUE, TRUE);
    ImgSetVisibility(image_progressbar_background, b_auto_install);
    ImgSetVisibility(image_progressbar_foreground, b_auto_install);
    label_install_progress.Visible := b_auto_install;
    if b_auto_install then
    begin tipStr := ExpandConstant('{cm:upta}'); end
    else begin tipStr := ExpandConstant('{cm:installing}'); end;
    label_install_progress.Caption := tipStr + ' 0%';
    label_install_progress.Left := (mainBkPanel.Width - label_install_progress.Width) div 2;
    label_install_progress.Top := app_name_label.Top + app_name_label.Height + 90;
    //<----------------------------------------------------------------------

    //错误提示文本 ----------------------------->
    update_failed_title := TLabel.Create(mainBkPanel);
    with update_failed_title do
    begin
        Parent := mainBkPanel;
        AutoSize := TRUE;
        Caption := ExpandConstant('{cm:updateFailedTitle}');
        Font.Name := 'Arial';
        Font.Size := 20;
        Font.Color := $808080;
        Transparent := TRUE;
        Left := (mainBkPanel.Width - Width) div 2;
        Top := (app_name_label.top + app_name_label.Height) + 40;
        Hide();
    end;
    update_failed_disc := TLabel.Create(mainBkPanel);
    with update_failed_disc do
    begin
        Parent := mainBkPanel;
        AutoSize := TRUE;
        Caption := ExpandConstant('{cm:updateFailedDisc}');
        Font.Name := 'Arial';
        Font.Size := 12;
        Font.Color := $291C14;
        Transparent := TRUE;
        Left := (mainBkPanel.Width - Width) div 2;
        Top := (update_failed_title.top + update_failed_title.Height) + 16;
        Hide();
    end;
    update_failed_link := TLabel.Create(mainBkPanel);
    with update_failed_link do
    begin
        Parent := mainBkPanel;
        AutoSize := TRUE;
        Caption := ExpandConstant('{cm:updateFailedLink}');
        Font.Name := 'Arial';
        Font.Size := 12;
        Font.Color := $FF8639;
        Transparent := TRUE;
        OnMouseDown := @button_anycubic_website_on_click;
        Cursor := crHand;
        Left := (mainBkPanel.Width - Width) div 2;
        Top := (update_failed_disc.top + update_failed_disc.Height) + 4;
        Hide();
    end;
    //<----------------------------------------------------

    //系统文件管理窗口弹出按钮 -------------------->
    button_browse := BtnCreate(mainBkPanel.Handle, 520, 520, 90, 38, ExpandConstant('{tmp}\button_browse_1.png'), 0, FALSE);
    BtnSetText(button_browse, ExpandConstant('{cm:browser}'));//按钮文字
    //文字字体
    button_browse_font := TFont.Create;
    with button_browse_font do begin
        Size := 11;
        Name := 'Arial';
        Color := $FF8639;
    end;
    //应用字体
    BtnSetFont(button_browse, button_browse_font.Handle);
    BtnSetFontColor(button_browse, $FF8639, $FFB080, $E0691D, $FCD6BD);
    BtnSetEvent(button_browse, ID_BUTTON_ON_CLICK_EVENT, WrapBtnCallback(@button_browse_on_click, 1));
    BtnSetVisibility(button_browse, FALSE);
    //<---------------------------------------------

    // 立即运行 ---------------------->
    button_run_now := BtnCreate(mainBkPanel.Handle, 238, 315, 191, 51, ExpandConstant('{tmp}\run_now_1.png'), 0, FALSE);
    BtnSetText(button_run_now, ExpandConstant('{cm:run_now}'));//按钮文字
    //文字字体
    button_run_now_font := TFont.Create;
    with button_run_now_font do begin
        Size := 18;
        Name := 'Arial';
        Color := $FF8639;
    end;
    //应用字体
    BtnSetFont(button_run_now, button_run_now_font.Handle);
    BtnSetFontColor(button_run_now, $FF8639, $FFB080, $E0691D, $FCD6BD);
    BtnSetEvent(button_run_now, ID_BUTTON_ON_CLICK_EVENT, WrapBtnCallback(@run_now_on_click, 1));
    BtnSetVisibility(button_run_now, FALSE);
    //<--------------------------------------------------------

    ImgApplyChanges(mainBkPanel.Handle);
    ImgApplyChanges(WizardForm.Handle);

    // 消息关闭窗口
    messagebox_close_create();
end;

procedure installFailureOccurred();
begin
    //update UI -------------->
    label_warn_tips.Hide();
    edit_target_path.Hide();
    label_disk_space.Hide();
    label_need_space.Hide();
    BtnSetVisibility(button_browse, FALSE);
    BtnSetVisibility(btn_more_options, FALSE);
    BtnSetVisibility(btn_more_options_close, FALSE);
    BtnSetVisibility(checkbox_license, FALSE);
    label_agree_title.Hide();
    label_agree_content.Hide();
    BtnSetVisibility(button_install_now, FALSE);
    ImgSetVisibility(image_progressbar_background, false);
    ImgSetVisibility(image_progressbar_foreground, false);
    label_install_progress.Visible := false;
    mainBkPanel.Height := WIZARDFORM_HEIGHT_NORMAL - WIZARDFORM_BORDER_WIDTH * 2;
    WizardForm.Height := WIZARDFORM_HEIGHT_NORMAL;
    ImgApplyChanges(mainBkPanel.Handle);
    BtnSetEnabled(button_close, false);
    BtnSetEnabled(button_minimize, false);

    update_failed_title.Show();
    update_failed_disc.Show();
    update_failed_link.Show();
    //-------------------------------------------->
end;

//安装页面改变时会调用这个函数
PROCEDURE CurPageChanged(CurPageID : INTEGER);
var
    b_app_running: boolean;
BEGIN
    IF (CurPageID = wpWelcome) THEN
    BEGIN
        if b_auto_install then
        begin
            //自动安装时候等待前一个程序退出，才可以进行安装
            b_app_running := IsAppRunning(ExpandConstant('{#MyAppExeName}'));
            if b_app_running then
            begin
                WizardForm.Visible := True;
                WizardForm.CancelButton.OnClick(WizardForm);
            end
            else
            begin
                //自动安装逻辑
                WizardForm.Visible := True;
                WizardForm.DirEdit.Text := p_auto_install;
                WizardForm.NextButton.OnClick(WizardForm);
            end;
        end
        else
        begin
            mainBkPanel.Height := WIZARDFORM_HEIGHT_NORMAL - WIZARDFORM_BORDER_WIDTH * 2;
            WizardForm.Height := WIZARDFORM_HEIGHT_NORMAL;
            label_warn_tips.Show();
            edit_target_path.Show();
            label_disk_space.Show();
            label_need_space.Show();
            BtnSetVisibility(button_browse, TRUE);
            BtnSetVisibility(btn_more_options, TRUE);
            BtnSetVisibility(btn_more_options_close, TRUE);
            BtnSetVisibility(checkbox_license, TRUE);
            label_agree_title.Show();
            label_agree_content.Show();
            BtnSetVisibility(button_install_now, TRUE);
        end;
    END;
    IF (CurPageID = wpInstalling) THEN
    BEGIN
        is_wizardform_show_normal := TRUE;
        label_warn_tips.Hide();
        edit_target_path.Hide();
        label_disk_space.Hide();
        label_need_space.Hide();
        BtnSetVisibility(button_browse, FALSE);
        BtnSetVisibility(btn_more_options, FALSE);
        BtnSetVisibility(btn_more_options_close, FALSE);
        BtnSetVisibility(checkbox_license, FALSE);
        label_agree_title.Hide();
        label_agree_content.Hide();
        BtnSetVisibility(button_install_now, FALSE);
        ImgSetVisibility(image_progressbar_background, TRUE);
        ImgSetVisibility(image_progressbar_foreground, TRUE);
        label_install_progress.Visible := TRUE;
        mainBkPanel.Height := WIZARDFORM_HEIGHT_NORMAL - WIZARDFORM_BORDER_WIDTH * 2;
        WizardForm.Height := WIZARDFORM_HEIGHT_NORMAL;
        ImgApplyChanges(mainBkPanel.Handle);
        BtnSetEnabled(button_close, false);
        BtnSetEnabled(button_minimize, false);
    END
    else
    begin
        BtnSetEnabled(button_close, true);
        BtnSetEnabled(button_minimize, true);
    end;
    IF (CurPageID = wpFinished) THEN
    BEGIN
        if b_auto_install then
        begin
            WizardForm.ClientWidth := ScaleX(0);
            WizardForm.ClientHeight := ScaleY(0);
            WizardForm.NextButton.OnClick(WizardForm);
        end
        else
        begin
            label_install_progress.Visible := FALSE;
            ImgSetVisibility(image_progressbar_background, FALSE);
            ImgSetVisibility(image_progressbar_foreground, FALSE);
            BtnSetVisibility(button_install_now, FALSE);
            BtnSetVisibility(button_run_now, TRUE);
            BtnSetEvent(button_run_now, ID_BUTTON_ON_CLICK_EVENT, WrapBtnCallback(@run_now_on_click, 1));
            BtnSetEvent(button_close, ID_BUTTON_ON_CLICK_EVENT, WrapBtnCallback(@run_now_on_click, 1));
            ImgApplyChanges(mainBkPanel.Handle);
        end;
    END;
END;

//指定跳过哪些标准页面
FUNCTION ShouldSkipPage(PageID : INTEGER) : BOOLEAN;
BEGIN
    IF (PageID = wpLicense) THEN Result := TRUE;
    IF (PageID = wpPassword) THEN Result := TRUE;
    IF (PageID = wpInfoBefore) THEN Result := TRUE;
    IF (PageID = wpUserInfo) THEN Result := TRUE;
    IF (PageID = wpSelectDir) THEN Result := TRUE;
    IF (PageID = wpSelectComponents) THEN Result := TRUE;
    IF (PageID = wpSelectProgramGroup) THEN Result := TRUE;
    IF (PageID = wpSelectTasks) THEN Result := TRUE;
    IF (PageID = wpReady) THEN Result := TRUE;
    IF (PageID = wpPreparing) THEN Result := TRUE;
    IF (PageID = wpInfoAfter) THEN Result := TRUE;
END;


function StrSplit(Text: String; Separator: String): TArrayOfString;
var
    i, p: Integer;
    Dest: TArrayOfString;
begin
    i := 0;
    repeat
        SetArrayLength(Dest, i+1);
        p := Pos(Separator,Text);
        if p > 0 then
        begin
            Dest[i] := Copy(Text, 1, p-1);
            Text := Copy(Text, p + Length(Separator), Length(Text));
            i := i + 1;
        end
        else
        begin
            Dest[i] := Text;
            Text := '';
        end;
    until Length(Text)=0;
    Result := Dest
end;

function RegisterSuffix(const Section, Key, Default, Filename: String): Boolean;
var
    customSuffixArray: TArrayOfString;
    suffix: String;
    index: Integer;
begin
    suffix := GetIniString(Section, Key, Default, Filename);
    customSuffixArray := StrSplit(suffix, ',');
    for index:= 0 to GetArrayLength(customSuffixArray)-1 do
    begin
        RegWriteStringValue(HKEY_CLASSES_ROOT, '.' + customSuffixArray[index], '', 'PhotonWorkShop');
    end;
    Result := true;
end;

procedure ChangeUninstallString;
var
    sUnInstPath: String;
    sUnInstallString: String;
    uicmd:String;
begin
    sUnInstPath := PRODUCT_REGISTRY_KEY;
    sUnInstallString := 'UninstallString';

    if RegQueryStringValue(HKEY_LOCAL_MACHINE, sUnInstPath, sUnInstallString, uicmd) then
    begin
        RegWriteStringValue(HKEY_LOCAL_MACHINE, sUnInstPath, sUnInstallString, ExpandConstant('"{app}/uninstall.exe"') + ' /verysilent /suppressmsgboxes /norestart');
    end
end;

//安装步骤改变时会调用这个函数
PROCEDURE CurStepChanged(CurStep : TSetupStep);
var
    ErrorCode: Integer;
    languageName: string;
    uicmd:String;
    pr, i1, i2 : Integer;
    updateContents: TArrayOfString;

begin        
    // Check if the current step is the finalization step and the installation failed
    i1 := WizardForm.ProgressGauge.Position - WizardForm.ProgressGauge.Min;
    i2 := WizardForm.ProgressGauge.Max - WizardForm.ProgressGauge.Min;
    pr := (i1 * 100) / i2;
    if (CurStep = ssPostInstall) and (not WizardSilent) and (not pr = 100) then
    begin
        //MsgBox('Installation failed. Please check your system configuration and try again.', mbError, MB_OK);
        // Optionally, you can perform additional actions here, such as logging the error or cleaning up temporary files
        // Abort the installation process
        installFailureOccurred();
        //WizardForm.Close;
    end;

    if(CurStep=ssDone) then
    begin
        languageName := ActiveLanguage();
        if 'cn' = languageName then
        begin
            RegWriteDWordValue(HKEY_CURRENT_USER, 'SOFTWARE\ANYCUBIC', 'language', 1)
        end
        else if 'en' = languageName then
        begin
            RegWriteDWordValue(HKEY_CURRENT_USER, 'SOFTWARE\ANYCUBIC', 'language', 0)
        end;

        RegisterSuffix('base_config', 'model_suffix', '', ExpandConstant('{app}/global_config.ini'));
        RegisterSuffix('base_config', 'slice_suffix', '', ExpandConstant('{app}/global_config.ini'));
        RegisterSuffix('base_config', 'scene_suffix', '', ExpandConstant('{app}/global_config.ini'));
        RegisterSuffix('base_config', 'custom_suffix', '', ExpandConstant('{app}/global_config.ini'));
        RegWriteStringValue(HKEY_CLASSES_ROOT, 'PhotonWorkShop', '', 'Program PhotonWorkShop');
        RegWriteStringValue(HKEY_CLASSES_ROOT, 'PhotonWorkShop\DefaultIcon', '', ExpandConstant('"{app}\{#MyAppExeName}",0'));
        RegWriteStringValue(HKEY_CLASSES_ROOT, 'PhotonWorkShop\shell\open\command', '', ExpandConstant('"{app}\{#MyAppExeName}" "%1"'));

        //是否是强制自动安装拉起
        SetIniBool('Launch', 'updatetips', b_auto_install, ExpandConstant('{app}/global_config.ini'));
        if b_auto_install then
        begin
            SetArrayLength(updateContents, 2);
            updateContents[0]:='[updatecontents]';
            updateContents[1]:=auto_install_version_info;
            SaveStringsToUTF8File(ExpandConstant('{app}\updatecontents'),updateContents,False);
        end;
        DelTree(ExpandConstant('{app}\configuration'), True, True, True);

        //ShellExec('open', ExpandConstant('{sys}\{#CmdName}'), ExpandConstant('cd /d {app}'), '', SW_HIDE, ewNoWait, ErrorCode);
        //ShellExec('open', ExpandConstant('{win}\{#ExeplorerName}'), ExpandConstant('{app}\{#MyAppExeName}'), '', SW_SHOWNORMAL, ewNoWait, ErrorCode);
        //ShellExec('open', ExpandConstant('{app}\{#MyAppExeName}'),'','', SW_SHOWNORMAL, ewNoWait, ErrorCode);
        if RegQueryStringValue(HKEY_CURRENT_USER, 'SOFTWARE\Microsoft\Windows NT\CurrentVersion\AppCompatFlags\Layers', ExpandConstant('{app}\{#MyAppExeName}'), uicmd) then
        begin
            RegDeleteValue(HKEY_CURRENT_USER, 'SOFTWARE\Microsoft\Windows NT\CurrentVersion\AppCompatFlags\Layers', ExpandConstant('{app}\{#MyAppExeName}'));
        end;
        ChangeUninstallString();
        //msgbox(ExpandConstant('{app}\Install.bat') + ', ' + ExpandConstant('.\{#MyAppExeName}'), mbInformation, MB_OK);
        ShellExec('open', ExpandConstant('{app}\Install.bat'), ExpandConstant('.\{#MyAppExeName}'), '', SW_HIDE, ewNoWait, ErrorCode);
    end;
END;

//卸载步骤改变时会调用此函数
PROCEDURE CurUninstallStepChanged(CurUninstallStep : TUninstallStep);
BEGIN
    IF (CurUninstallStep = usAppMutexCheck) THEN
    BEGIN
    //此阶段为检查应用程序互斥的阶段，请在此进行互斥操作
    END;
END;

function InitializeUninstall(): Boolean;
var
    ErrorCode: INTEGER;
begin
    ShellExec('open', ExpandConstant('"{app}/uninstall.exe"'), '', '', SW_HIDE, ewNoWait, ErrorCode);
    Result := FALSE;
end;

